﻿using Abide.UI_Elements;
using Abide_AddOn_API.Classes;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Xml;

namespace Abide
{
    [ComVisible(true)]
    public partial class Main : Form
    {
        const string UpdateUrl = "https://dl.dropboxusercontent.com/u/238557949/Potential%20Software/Abide/Update.xml";

        public Main()
        {
            InitializeComponent();
        }
        
        void LoadRecentMaps()
        {
            //Prepare
            MenuItem RecentMap = null;
            this.FileSeparator1.Visible = false;

            //Re-add...
            this.RecentCEMaps.MenuItems.Clear();
            this.RecentCEMaps.MenuItems.Add(ClearCEMaps);
            this.RecentCEMaps.MenuItems.Add(menuItem1);
            this.RecentH2Maps.MenuItems.Clear();
            this.RecentH2Maps.MenuItems.Add(ClearH2Maps);
            this.RecentH2Maps.MenuItems.Add(menuItem2);
            this.RecentH2BMaps.MenuItems.Clear();
            this.RecentH2BMaps.MenuItems.Add(ClearH2BMaps);
            this.RecentH2BMaps.MenuItems.Add( menuItem3);
            this.RecentH3Maps.MenuItems.Clear();
            this.RecentH3Maps.MenuItems.Add(ClearH3Maps);
            this.RecentH3Maps.MenuItems.Add(menuItem4);
            this.RecentH3BetaMaps.MenuItems.Clear();
            this.RecentH3BetaMaps.MenuItems.Add(ClearH3BMaps);
            this.RecentH3BetaMaps.MenuItems.Add(menuItem5);
            this.RecentHRMaps.MenuItems.Clear();
            this.RecentHRMaps.MenuItems.Add(ClearHRMaps);
            this.RecentHRMaps.MenuItems.Add(menuItem6);

            //Load
            #region Halo CE Maps
            this.RecentCEMaps.Enabled = false;
            this.RecentCEMaps.Visible = false;
            for (int i = 0; i < Settings.RecentMaps_CE.Count; i++)
            {
                //Check if it's not null or blank...
                if (string.IsNullOrEmpty(Settings.RecentMaps_CE[i]))
                    continue;

                //Check to make sure it exists...
                if (!System.IO.File.Exists(Settings.RecentMaps_CE[i]))
                    continue;

                //Set Path
                string Path = Settings.RecentMaps_CE[i];

                //Add Menu Item
                RecentMap = new MenuItem(string.Format("&{0}: {1}", i.ToString(), Path));
                RecentMap.Tag = Settings.RecentMaps_CE[i];
                RecentMap.Click += new EventHandler(RecentMap_Click);
                this.RecentCEMaps.MenuItems.Add(RecentMap);
                this.RecentCEMaps.Enabled = true;
                this.RecentCEMaps.Visible = true;
                this.FileSeparator1.Visible = true;
            }
            #endregion
            #region Halo 2 Maps
            this.RecentH2Maps.Enabled = false;
            this.RecentH2Maps.Visible = false;
            for (int i = 0; i < Settings.RecentMaps_H2.Count; i++)
            {
                //Check if it's not null or blank...
                if (string.IsNullOrEmpty(Settings.RecentMaps_H2[i]))
                    continue;

                //Check to make sure it exists...
                if (!System.IO.File.Exists(Settings.RecentMaps_H2[i]))
                    continue;

                //Set Path
                string Path = Settings.RecentMaps_H2[i];

                //Add Menu Item
                RecentMap = new MenuItem(string.Format("&{0}: {1}", i.ToString(), Path));
                RecentMap.Tag = Settings.RecentMaps_H2[i];
                RecentMap.Click += new EventHandler(RecentMap_Click);
                this.RecentH2Maps.MenuItems.Add(RecentMap);
                this.RecentH2Maps.Enabled = true;
                this.RecentH2Maps.Visible = true;
                this.FileSeparator1.Visible = true;
            }
            #endregion
            #region Halo 2 Beta Maps
            this.RecentH2BMaps.Enabled = false;
            this.RecentH2BMaps.Visible = false;
            for (int i = 0; i < Settings.RecentMaps_H2B.Count; i++)
            {
                //Check if it's not null or blank...
                if (string.IsNullOrEmpty(Settings.RecentMaps_H2B[i]))
                    continue;

                //Check to make sure it exists...
                if (!System.IO.File.Exists(Settings.RecentMaps_H2B[i]))
                    continue;

                //Set Path
                string Path = Settings.RecentMaps_H2B[i];

                //Add Menu Item
                RecentMap = new MenuItem(string.Format("&{0}: {1}", i.ToString(), Path));
                RecentMap.Tag = Settings.RecentMaps_H2B[i];
                RecentMap.Click += new EventHandler(RecentMap_Click);
                this.RecentH2BMaps.MenuItems.Add(RecentMap);
                this.RecentH2BMaps.Enabled = true;
                this.RecentH2BMaps.Visible = true;
                this.FileSeparator1.Visible = true;
            }
            #endregion
            #region Halo 3 Maps
            this.RecentH3Maps.Enabled = false;
            this.RecentH3Maps.Visible = false;
            for (int i = 0; i < Settings.RecentMaps_H3.Count; i++)
            {
                //Check if it's not null or blank...
                if (string.IsNullOrEmpty(Settings.RecentMaps_H3[i]))
                    continue;

                //Check to make sure it exists...
                if (!System.IO.File.Exists(Settings.RecentMaps_H3[i]))
                    continue;

                //Set Path
                string Path = Settings.RecentMaps_H3[i];

                //Add Menu Item
                RecentMap = new MenuItem(string.Format("&{0}: {1}", i.ToString(), Path));
                RecentMap.Tag = Settings.RecentMaps_H3[i];
                RecentMap.Click += new EventHandler(RecentMap_Click);
                this.RecentH3Maps.MenuItems.Add(RecentMap);
                this.RecentH3Maps.Enabled = true;
                this.RecentH3Maps.Visible = true;
                this.FileSeparator1.Visible = true;
            }
            #endregion
            #region Halo 3 Beta Maps
            this.RecentH3BetaMaps.Enabled = false;
            this.RecentH3BetaMaps.Visible = false;
            for (int i = 0; i < Settings.RecentMaps_H3B.Count; i++)
            {
                //Check if it's not null or blank...
                if (string.IsNullOrEmpty(Settings.RecentMaps_H3B[i]))
                    continue;

                //Check to make sure it exists...
                if (!System.IO.File.Exists(Settings.RecentMaps_H3B[i]))
                    continue;

                //Set Path
                string Path = Settings.RecentMaps_H3B[i];

                //Add Menu Item
                RecentMap = new MenuItem(string.Format("&{0}: {1}", i.ToString(), Path));
                RecentMap.Tag = Settings.RecentMaps_H3B[i];
                RecentMap.Click += new EventHandler(RecentMap_Click);
                this.RecentH3BetaMaps.MenuItems.Add(RecentMap);
                this.RecentH3BetaMaps.Enabled = true;
                this.RecentH3BetaMaps.Visible = true;
                this.FileSeparator1.Visible = true;
            }
            #endregion
            #region Halo Reach Maps
            this.RecentHRMaps.Enabled = false;
            this.RecentHRMaps.Visible = false;
            for (int i = 0; i < Settings.RecentMaps_HR.Count; i++)
            {
                //Check if it's not null or blank...
                if (string.IsNullOrEmpty(Settings.RecentMaps_HR[i]))
                    continue;

                //Check to make sure it exists...
                if (!System.IO.File.Exists(Settings.RecentMaps_HR[i]))
                    continue;

                //Set Path
                string Path = Settings.RecentMaps_HR[i];

                //Add Menu Item
                RecentMap = new MenuItem(string.Format("&{0}: {1}", i.ToString(), Path));
                RecentMap.Tag = Settings.RecentMaps_HR[i];
                RecentMap.Click += new EventHandler(RecentMap_Click);
                this.RecentHRMaps.MenuItems.Add(RecentMap);
                this.RecentHRMaps.Enabled = true;
                this.RecentHRMaps.Visible = true;
                this.FileSeparator1.Visible = true;
            }
            #endregion
        }
        void Item_Click(object sender, EventArgs e)
        {
            throw new NotImplementedException();
        }
        void RecentMap_Click(object sender, EventArgs e)
        {
            MenuItem Sender = sender as MenuItem;

            if (Sender != null)
            {
                //Load Map...
                LoadMap(Sender.Tag as string);
            }
        }

        private void Main_Load(object sender, EventArgs e)
        {
            //Close
            Program.CloseSplash();

            //Set Version
            VersionItem.Text = "v" + Application.ProductVersion;

            //Load Recent Map List...
            LoadRecentMaps();

            //Open Maps?
            foreach (string Map in Program.Maps)
                LoadMap(Map);
        }
        private void OpenItem_Click(object sender, EventArgs e)
        {
            using (FileDialog OpenDlg = new OpenFileDialog())
            {
                OpenDlg.Title = "Select Halo 2 Map to Load...";
                OpenDlg.Filter = "Halo 2 Maps (*.map)|*.map";

                if (OpenDlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                {
                    //Load...
                    LoadMap(OpenDlg.FileName);
                }
            }
        }
        private void LoadMap(string FileLocation)
        {
            if (System.IO.File.Exists(FileLocation))
            {
                //Disable...
                this.Enabled = false;

                //Allow all operations to finish...
                System.Threading.Thread.Sleep(0);

                //Create TabPage
                Form MapForm = new Form();
                MapForm.Size = new System.Drawing.Size(720, 480);
                MapForm.MdiParent = this;
                MapForm.Icon = Properties.Resources.Unknown_Map;

                //Prepare Variables
                List<string> RecentMaps;
                Control MapControl;

                //Get Version
                switch (MapHelper.GetVersion(FileLocation))
                {
                    case Abide_Halo_Library.MapVersion.Halo_2:
                        //Add To Recent Maps
                        RecentMaps = Settings.RecentMaps_H2;
                        RecentMaps.Remove(FileLocation);
                        RecentMaps.Insert(0, FileLocation);
                        Settings.RecentMaps_H2 = RecentMaps;

                        //Create MapControl...
                        MapControl = new UI_Elements.Halo_2.MapControl(FileLocation);
                        MapControl.Dock = DockStyle.Fill;
                        MapForm.Controls.Add(MapControl);
                        break;

                    case Abide_Halo_Library.MapVersion.Halo_2b:
                        //Add To Recent Maps
                        RecentMaps = Settings.RecentMaps_H2B;
                        RecentMaps.Remove(FileLocation);
                        RecentMaps.Insert(0, FileLocation);
                        Settings.RecentMaps_H2B = RecentMaps;

                        //Create MapControl...
                        MapControl = new UI_Elements.Halo_2_Beta.MapControl(FileLocation);
                        MapControl.Dock = DockStyle.Fill;
                        MapForm.Controls.Add(MapControl);
                        break;
                }

                //Rename...
                MapForm.WindowState = FormWindowState.Maximized;

                //Add Form
                MapForm.Show();

                //Enable
                this.Enabled = true;
                this.Focus();

                //Handle recent Maps
                LoadRecentMaps();
            }
        }
        private void OptionsItem_Click(object sender, EventArgs e)
        {
            //Show Options...
            using (Forms.SettingsForm OptDlg = new Forms.SettingsForm(this))
            {
                OptDlg.ShowDialog();
            }
        }
        private void ExitItem_Click(object sender, EventArgs e)
        {
            //Exit...
            Application.Exit();
        }
        private void OpenXboxWindowItem_Click(object sender, EventArgs e)
        {
            //Prepare Tab and Control
            Form XboxForm = new Form();
            XboxForm.Icon = Properties.Resources.Xbox;
            XboxForm.Text = "Xbox";
            XboxForm.Size = new System.Drawing.Size(720, 480);
            XboxControl XboxCtrl = new XboxControl();
            XboxCtrl.Dock = DockStyle.Fill;
            XboxForm.Controls.Add(XboxCtrl);

            //Add Form
            XboxForm.MdiParent = this;
            XboxForm.Show();
        }
        private void QuickConnectItem_Click(object sender, EventArgs e)
        {
            try
            {
                //Initialize
                if (Program.Xbox.Xbox == null)
                    Program.Xbox.Xbox = new YeloDebug.Xbox();

                //Check
                if (Program.Xbox.Xbox.Connected)
                    Program.Xbox.Xbox.Disconnect();
                else
                    Program.Xbox.Xbox.Connect();
            }
            catch { }
            finally { Program.ChangeXbox(sender); }
        }
        private void CreateAddOnItem_Click(object sender, EventArgs e)
        {
            using (OpenFileDialog OpenDlg = new OpenFileDialog())
            {
                //Prepare
                OpenDlg.Filter = "Abide AddOn Assemblies (*.dll,*.exe)|*.dll;*.exe|All Files (*.*)|*.*";

                //Open?
                if (OpenDlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                {
                    if (Classes.AbideAddOnManager.IsAddOn(OpenDlg.FileName))
                    {
                        //Get Directory
                        string Directory = System.IO.Path.GetDirectoryName(OpenDlg.FileName);

                        //Save the AddOn Package
                        using (SaveFileDialog SaveDlg = new SaveFileDialog())
                        {
                            //Prepare
                            SaveDlg.Title = "Save Abide AddOn Package";
                            SaveDlg.Filter = "Abide AddOn Package (*.aao)|*.aao|Compressed Zip Folder (*.zip)|*.zip";
                            SaveDlg.FileName = OpenDlg.SafeFileName.Replace(".exe", string.Empty).Replace(".dll", string.Empty);

                            //Save?
                            if (SaveDlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                            {
                                //Prepare
                                DirectoryInfo DInfo = new DirectoryInfo(Directory);
                                FileInfo FInfo = new FileInfo(SaveDlg.FileName);

                                //Show
                                using (Abide.Forms.CreateAddOnDialog CreateDlg = new Forms.CreateAddOnDialog())
                                {
                                    //Setup
                                    CreateDlg.AddOnName = FInfo.Name.Replace(".aao", string.Empty);
                                    CreateDlg.LoadFiles(Directory);

                                    //Show
                                    if (CreateDlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                                    {
                                        //Copy
                                        File.Copy(CreateDlg.CreateZip(Directory, OpenDlg.FileName), SaveDlg.FileName, true);
                                        MessageBox.Show("Done.");
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        private void FileAssociationsItem_Click(object sender, EventArgs e)
        {
            using (Forms.AssociationForm af = new Forms.AssociationForm())
                af.ShowDialog();
        }
        private void ManageAddOnsItem_Click(object sender, EventArgs e)
        {
            Forms.AddOnManager AddOnManager = new Forms.AddOnManager();
            AddOnManager.ShowDialog();
        }
        private void TileVertItem_Click(object sender, EventArgs e)
        {
            this.LayoutMdi(MdiLayout.TileVertical);
        }
        private void TileHorItem_Click(object sender, EventArgs e)
        {
            this.LayoutMdi(MdiLayout.TileHorizontal);
        }
        private void CascadeItem_Click(object sender, EventArgs e)
        {
            this.LayoutMdi(MdiLayout.Cascade);
        }
        private void ClearCEMaps_Click(object sender, EventArgs e)
        {
            Settings.RecentMaps_CE = new List<string>(); LoadRecentMaps();
        }
        private void ClearH2Maps_Click(object sender, EventArgs e)
        {
            Settings.RecentMaps_H2 = new List<string>(); LoadRecentMaps();
        }
        private void ClearH2BMaps_Click(object sender, EventArgs e)
        {
            Settings.RecentMaps_H2B = new List<string>(); LoadRecentMaps();
        }
        private void ClearH3Maps_Click(object sender, EventArgs e)
        {
            Settings.RecentMaps_H3 = new List<string>(); LoadRecentMaps();
        }
        private void ClearH3BetaMaps_Click(object sender, EventArgs e)
        {
            Settings.RecentMaps_H3B = new List<string>(); LoadRecentMaps();
        }
        private void ClearHRMaps_Click(object sender, EventArgs e)
        {
            Settings.RecentMaps_HR = new List<string>(); LoadRecentMaps();
        }
        private void CloseAllItem_Click(object sender, EventArgs e)
        {
            //Close All Child Windows
            foreach (Form Child in MdiChildren)
            {
                Child.Close();
                Child.Dispose();
            }
        }
        private void ConsoleLogItem_Click(object sender, EventArgs e)
        {
            Program.Log.Show();
        }
        private void CodePlexItem_Click(object sender, EventArgs e)
        {
            Process.Start("http://abide.codeplex.com/");
        }
        private void RemnantItem_Click(object sender, EventArgs e)
        {
            Process.Start("http://remnantmods.com/forums");
        }
        private void BugItem_Click(object sender, EventArgs e)
        {
            Process.Start("https://abide.codeplex.com/workitem/list/basic");
        }
        private void CommentItem_Click(object sender, EventArgs e)
        {
            Process.Start("https://abide.codeplex.com/discussions");
        }
        private void CheckForUpdatesItem_Click(object sender, EventArgs e)
        {
            //Check
            if (!Classes.Networking.IsConnected())
                MessageBox.Show("Unable to contact download servers.", "Uh oh!");
            else
            {
                //Create Target
                string UpdaterPath = Path.Combine(Application.StartupPath, "Abide Updater.exe");

                //Check Update
                XmlDocument Document = new XmlDocument();
                Document.Load(UpdateUrl);

                //Open Abide Node
                XmlNode Abide = Document["Abide"];

                //Read Elements
                XmlNode Latest = Abide["Latest"];
                XmlNode Date = Abide["Date"];
                XmlNode Updater = Abide["Updater"];
                XmlNode Notes = Abide["Notes"];

                //Compare
                AssemblyName Name = new AssemblyName(Latest.InnerText);
                AssemblyName Executing = Assembly.GetExecutingAssembly().GetName();
                DateTime CreatedDate = DateTime.Parse(Date.InnerText);
                string UpdaterUrl = Updater.InnerText;
                string PatchNotes = Notes.InnerText;

                //Compare
                if (Executing.Version < Name.Version || Program.ForceUpdate)
                {
                    if (MessageBox.Show("An update is available. Would you like to launch the Abide Updater?",
                        "Update Available", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.Yes)
                    {
                        //WebClient
                        WebClient client = new WebClient();
                        client.DownloadFile(UpdaterUrl, UpdaterPath);
                        client.Dispose();

                        //Launch
                        Process.Start(UpdaterPath, Application.StartupPath);

                        //Exit
                        Application.Exit();
                    }
                }
                else
                    MessageBox.Show("Abide is up to date.", "No Updates");
            }
        }
        private void Main_DragEnter(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                bool OK = false;
                string[] Files = (string[])e.Data.GetData(DataFormats.FileDrop);
                if (Files != null)
                {
                    foreach (string File in Files)
                    {
                        FileInfo Info = new FileInfo(File);
                        OK |= (Info.Extension == ".map" || Info.Extension == ".aao" || Info.Extension == ".atp");
                    }
                    e.Effect = OK ? DragDropEffects.Copy : DragDropEffects.None;
                }
                else
                    e.Effect = DragDropEffects.None;
            }
        }
        private void Main_DragDrop(object sender, DragEventArgs e)
        {
            string[] Files = (string[])e.Data.GetData(DataFormats.FileDrop);
            if(Files != null)
                foreach (string File in Files)
                {
                    FileInfo Info = new FileInfo(File);
                    switch (Info.Extension.Remove(0, 1))
                    {
                        case "map":
                            LoadMap(File);
                            break;

                        case "aao":
                            string AddOnPath = Path.Combine(Program.AddOnsPath, Info.Name.Replace(Info.Extension, string.Empty));

                            //Extract
                            Classes.ZipOperations.ExtractZipFile(File, string.Empty, AddOnPath);

                            //Installed
                            MessageBox.Show("AddOn Installed.");
                            break;
                    }
                }
        }
    }
}
